#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QInputDialog>
#include <QStringList>
#include <QUrl>
#include "DiscussPane.h"

MainWindow::MainWindow(QWidget *parent) :
		QMainWindow(parent),
		ui(new Ui::MainWindow),
		nickname("Anonymous"),
		settings("01Lut", "01Lut")
{

	setAttribute(Qt::WA_DeleteOnClose, false);
	privatePanes = new QList<DiscussPane*>();
	mainPane = new DiscussPane(-1, this);
	connect(mainPane, SIGNAL(toRead(DiscussPane*)), this, SLOT(onToRead(DiscussPane*)));

	icon = new QIcon(":/img/icon.png");
	iconWarn = new QIcon(":/img/iconW.png");
	trayIcon = new QSystemTrayIcon(*icon);
	this->setWindowIcon(*icon);

	trayIcon->show();

	QDir home = QDir::home();
	nickname = settings.value("nickname", home.dirName()).toString();

	serverIP = settings.value("server", "127.0.0.1").toString();
	serverPort = settings.value("port", 1888).toInt();
	showTime = settings.value("time", true).toBool();

	QString tmp = settings.value("server").toString();
	if(tmp.size() < 1)
	{

		QString ipServer = QInputDialog::getText(this, "server address", "Server address :", QLineEdit::Normal, "127.0.0.1:1888");
		QStringList serverInfos = ipServer.split(":");
		if(serverInfos.size()>1)
			serverPort = serverInfos.at(1).toInt();

		settings.setValue("server", serverInfos.at(0));
		settings.setValue("port", serverPort);
		serverIP = serverInfos.at(0);
	}


    ui->setupUi(this);

	exitAct = new QAction("Quit", this);
	exitAct->setShortcut(QKeySequence::Quit);
	connect(exitAct, SIGNAL(triggered()), this, SLOT(onExitAct()));
	ui->menuTools->addAction(exitAct);

	menuTray= new QMenu("01Lut");
	menuTray->addAction(exitAct);
	trayIcon->setContextMenu(menuTray);

	sock = new QTcpSocket(this);
	connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorReceived(QAbstractSocket::SocketError)));
	connect(sock, SIGNAL(readyRead()), this, SLOT(dataHandler()));
	connect(sock, SIGNAL(connected()), this, SLOT(onConnected()));
	QString str = "Connecting to server at ";
	str += serverIP + " on port " + QString::number(serverPort) + "\n";
	mainPane->displayInfo(str);

	sock->connectToHost(serverIP, serverPort);

	connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(onTabChanged(int)));
	connect(ui->listWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onItemDoubleClicked(QModelIndex)));
	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onTrayClicked(QSystemTrayIcon::ActivationReason)));

	notifications = settings.value("notifications", true).toBool();

	ui->actionNotifications->setChecked(notifications);
	ui->actionShow_time->setChecked(showTime);

	QHBoxLayout *l = static_cast<QHBoxLayout*>(ui->mainTab->layout());
	l->insertWidget(0, mainPane, 6);
	l->setStretch(1, 1);
	onTabChanged(0);


}


bool MainWindow::getShowTime()
{
	return showTime;
}

void MainWindow::initMainWindow()
{
	ui->listWidget->setModel(LutController::getInstance()->getUsers());
}

void MainWindow::onTabChanged(int id)
{
	if(id>0)
	{
		ui->actionClose_current_tab->setEnabled(true);
	}
	else
	{
		ui->actionClose_current_tab->setEnabled(false);
	}
	ui->tabWidget->setTabIcon(id, QIcon());
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::errorReceived(QAbstractSocket::SocketError socketError)
{
	QString str;
	if(socketError == QAbstractSocket::ConnectionRefusedError)
	{
		str = "::Cannot connect to server... Aborting.\n";
	}
	else
	{
		str =":: Server error\n";
	}

	mainPane->displayError(str);
	for(int i=0; i<privatePanes->size(); i++)
	{
		privatePanes->at(i)->displayError(str);
	}
	this->activateWindow();
}

void MainWindow::sendMsg(QString str)
{
	if(str.size() > 0)
	{
		QByteArray data = "MSG ";
		str.replace(QChar(8364), "%E2%82%AC");
		data.append(str);
		sock->write(data);
	}
}

void MainWindow::sendPrivateMsg(int to, QString str)
{
	if(str.size() > 0)
	{
		QByteArray data = "PMSG ";
		data.append(QString::number(to)+" ");
		str.replace(QChar(8364), "%E2%82%AC");
		data.append(str);
		sock->write(data);
	}
}

void MainWindow::dataHandler()
{
	while(sock->bytesAvailable()>0)
	{
		char c;
		QByteArray data;
		do {
			sock->read(&c, 1);
			data.append(c);
		} while ( c != EOF );

		data.remove(data.size()-1, 1);

		if(data.indexOf("MSG ") == 0)
		{
			QString str(data.remove(0, 4));
			QStringList parts = str.split(" ");
			int pos = str.indexOf(" ");
			str = str.remove(0, pos+1);

			// TODO: displaymsg(str)
			mainPane->displayMsg(parts.at(0).toInt(), str);

			// ----------------------
			// ---- Notifications ---
			if(!isActiveWindow())
			{
				trayIcon->setIcon(*iconWarn);
				if(notifications)
					trayIcon->showMessage("New message from "+LutController::getInstance()->getNameFromId(parts.at(0).toInt()), str);
			}
		}
		else if(data.indexOf("PMSG ") == 0)
		{
			QString str(data.remove(0, 5));
			QStringList parts = str.split(" ");
			int pos = str.indexOf(" ");
			str = str.remove(0, pos+1);


			DiscussPane *pane = findPaneById(parts.at(0).toInt());
			if(!pane)
			{
				int gid = parts.at(0).toInt();
				QString gname = LutController::getInstance()->getUsers()->getNameById(gid);

				pane = new DiscussPane(gid, this);
				privatePanes->append(pane);
				ui->tabWidget->addTab(pane, gname);
				connect(pane, SIGNAL(toRead(DiscussPane*)), this, SLOT(onToRead(DiscussPane*)));
			}
			pane->displayMsg(parts.at(0).toInt(), str);

			// ----------------------
			// ---- Notifications ---
			if(!isActiveWindow())
			{
				trayIcon->setIcon(*iconWarn);
				if(notifications)
					trayIcon->showMessage("New message from "+LutController::getInstance()->getNameFromId(parts.at(0).toInt()), str);
			}
		}
		else if(data.indexOf("NICK ") == 0)
		{
			QString str(data.remove(0, 5));
			int pos = str.indexOf(" ");

			int userId = str.left(pos).toInt();
			QString info = LutController::getInstance()->getNameFromId(userId)+" is now known as "+ str.mid(pos+1)+"\n";
			DiscussPane *pane = findPaneById(userId);
			if(pane)
				pane->displayInfo(info);
			mainPane->displayInfo(info);

			sock->write("LIST");
		}
		else if(data.indexOf("NC ") == 0)
		{
			QString str(data.remove(0, 3));
			mainPane->displayInfo(str + " has join.\n");

			sock->write("LIST");
		}
		else if(data.indexOf("LEAVE ") == 0)
		{
			int idClient = data.remove(0, 6).toInt();

			QString info = LutController::getInstance()->getNameFromId(idClient)+" has left.\n";
			DiscussPane *pane = findPaneById(idClient);
			if(pane)
			{
				pane->displayInfo(info);
				pane->setGuyId(0);
			}

			mainPane->displayInfo(info);

			LutController::getInstance()->getUsers()->removeRowById(idClient);

			sock->write("LIST");
		}
		else if(data.indexOf("YID ") == 0)
		{
			id = data.remove(0, 4).toInt();
		}
		else if(data.indexOf("LIST ") == 0)
		{
			QString str = data.remove(0, 5);
			QStringList users = str.split(" ; ");
			majUserList(users);
		}

	}

}

DiscussPane* MainWindow::findPaneById(int id)
{
	for(int i=0; i<privatePanes->size(); i++)
	{
		if(privatePanes->at(i)->getGuyId() == id)
			return privatePanes->at(i);
	}
	return 0;
}



void MainWindow::on_actionChange_nickname_triggered()
{
	QString n = QInputDialog::getText(this, "Nickname", "Choose a nickname", QLineEdit::Normal, nickname);
	if(n.size()>0)
	{
		QByteArray data = "NICK ";
		data.append(n);
		sock->write(data);
		nickname = n;
		settings.setValue("nickname", nickname);
	}
}


void MainWindow::onConnected()
{
	QString str = "Connected\n";
	mainPane->displayInfo(str);
	for(int i=0; i<privatePanes->size(); i++)
	{
		privatePanes->at(i)->displayInfo(str);
	}
	QByteArray data = "NICK ";
	data.append(nickname);
	sock->write(data);
}


bool MainWindow::event ( QEvent *event  )
{
	if(event->type() == QEvent::WindowActivate)
		trayIcon->setIcon(*icon);
	return QMainWindow::event(event);
}

void MainWindow::onItemDoubleClicked(QModelIndex index)
{
	int gid = LutController::getInstance()->getUsers()->data(index,Qt::UserRole).toInt();
	QString gname = LutController::getInstance()->getUsers()->data(index,Qt::DisplayRole).toString();
	DiscussPane *p = findPaneById( gid );
	if( !p )
	{
		p = new DiscussPane(gid, this);
		privatePanes->append(p);
		int i = ui->tabWidget->addTab(p, gname);
		ui->tabWidget->setCurrentIndex(i);

		connect(p, SIGNAL(toRead(DiscussPane*)), this, SLOT(onToRead(DiscussPane*)));
	}
	else
	{
		int panePos = ui->tabWidget->indexOf(p);
		ui->tabWidget->setCurrentIndex(panePos);
	}
}

void MainWindow::onToRead(DiscussPane *p)
{
	int i = ui->tabWidget->indexOf(p);
	i = i<0?0:i;
	if(i != ui->tabWidget->currentIndex())
	{
		ui->tabWidget->setTabIcon(i, QIcon(":/img/warn.png"));
	}
}

void MainWindow::onTrayClicked(QSystemTrayIcon::ActivationReason r)
{
	if(r == QSystemTrayIcon::Trigger)
	{
		if(isVisible())
			close();
		else
			show();
	}
}


void MainWindow::on_actionChange_server_triggered()
{
	serverPort = 1888;
	QString ipServer = QInputDialog::getText(this, "server address", "Server address :", QLineEdit::Normal, serverIP+":"+QString::number(serverPort));
	QStringList serverInfos = ipServer.split(":");
	if(ipServer.size()>0)
	{
		if(serverInfos.size()>1)
			serverPort = serverInfos.at(1).toInt();

		serverIP = serverInfos.at(0);
		settings.setValue("server", serverIP);
		settings.setValue("port", serverPort);

		sock->disconnectFromHost();

		sock->connectToHost(serverIP, serverPort);

		QString str = "Connecting to server at ";
		str += serverIP + " on port " + QString::number(serverPort) + "\n";
		mainPane->displayInfo(str);
		privatePanes->clear();
		for(int i=1; i<ui->tabWidget->count(); i++)
		{
			ui->tabWidget->removeTab(i);
		}
		LutController::getInstance()->getUsers()->clear();
	}
}

int MainWindow::myId()
{
	return id;
}

void MainWindow::majUserList(QStringList list)
{
	for (int i=0; i<list.size(); i++)
		if(list.at(i) != "")
			majUser(list.at(i));

}

void MainWindow::majUser(QString data)
{
	QStringList infos = data.split(" ");
	int uid = infos.at(0).toInt();
	LutController::getInstance()->getUsers()->addOrReplace(new User(data));

	DiscussPane *pane = findPaneById(uid);
	if(pane)
	{
		int idpane = ui->tabWidget->indexOf(pane);
		ui->tabWidget->setTabText(idpane, LutController::getInstance()->getNameFromId(uid));
	}
}

void MainWindow::on_actionNotifications_toggled(bool v)
{
	notifications = v;
	settings.setValue("notifications", v);
}

void MainWindow::on_actionClose_current_tab_triggered()
{
	DiscussPane *p = static_cast<DiscussPane*>(ui->tabWidget->currentWidget());
	privatePanes->removeOne(p);
	ui->tabWidget->removeTab(ui->tabWidget->currentIndex());

}

void MainWindow::onExitAct()
{
	LutController::getInstance()->onQuitReq();
}

void MainWindow::on_actionShow_time_triggered()
{

}

void MainWindow::on_actionShow_time_toggled(bool v)
{
	showTime = v;
	settings.setValue("time", v);
}

void MainWindow::on_actionClear_triggered()
{
	DiscussPane *p;
	p = ui->tabWidget->currentIndex() > 0 ? static_cast<DiscussPane*>(ui->tabWidget->currentWidget()) : mainPane;
	p->clearPane();
}
